﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AudiPyme.DAL;

namespace AudiPyme.BLL
{
    public class AnalisisRiesgoNegocio
    {
        //Método que inserta los elementos de Análisis de Riesgo calculados en el informe
        public static void InsertaAnalisisRiesgo(List<RiesgoActivo> MatrizRiesgos, int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Por cada activo
            for (int i = 0; i < MatrizRiesgos.Count; i++)
            {
                //Para cada Amenaza
                for (int j = 0; j < MatrizRiesgos[i].NivelRiesgoAmenaza.Count; j++)
                {
                    //Para los Controles NO/PARC de cada Amenaza
                    for (int k = 0; k < MatrizRiesgos[i].NivelRiesgoAmenaza[j].ControlesNoParc.Count; k++)
                    {
                        //Una nueva instancia Análisis de Riesgo por cada tupla (Activo,Amenaza,Control) distinta
                        AnalisisRiesgo nuevoAR = new AnalisisRiesgo();
                        nuevoAR.IdActivo = MatrizRiesgos[i].IdActivo;
                        nuevoAR.Riesgo = MatrizRiesgos[i].MaximoRiesgoActivo;
                        nuevoAR.IdAmenaza = MatrizRiesgos[i].NivelRiesgoAmenaza[j].IdAmenaza;
                        nuevoAR.IdControl = MatrizRiesgos[i].NivelRiesgoAmenaza[j].ControlesNoParc[k].IdControl;
                        nuevoAR.IdInforme = IdInforme;
                        agenteBD.AddToAnalisisRiesgoEstablecer(nuevoAR);
                    }//fin k
                }//fin j
            }//fin i
            //Insertamos en la BD
            agenteBD.SaveChanges();
        }


        //Recoge toda la información relacionada de Análisis de Riesgo de un Informe y la formatea para mostrarla en una tabla del informe
        public static List<AnalisisRiesgoDatosInforme> RecogeAnalisRiesgoInforme(int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<AnalisisRiesgo> AnalisisRiesgoEmpresa = AnalisisRiesgoFactory.AnalisisRiesgoEmpresa(IdInforme);
            List<AnalisisRiesgoDatosInforme> LAnalisisRiesgo = new List<AnalisisRiesgoDatosInforme>();
            LAnalisisRiesgo = (from INF in agenteBD.InformesEstablecer
                               join AR in agenteBD.AnalisisRiesgoEstablecer on INF.IdInforme equals AR.IdInforme
                               join AI in agenteBD.ActivosInformeEstablecer on AR.IdActivo equals AI.IdActivo
                               join AE in agenteBD.ActivosEmpresaEstablecer on AI.IdActivo equals AE.IdActivo
                               join AM in agenteBD.AmenazasEstablecer on AR.IdAmenaza equals AM.IdAmenaza
                               join CE in agenteBD.ControlesEmpresaInformeEstablecer on AR.IdInforme equals CE.IdInforme
                               where AR.IdControl == CE.IdControl && AI.IdInforme == IdInforme && INF.IdInforme == IdInforme && CE.IdInforme == IdInforme
                               select new AnalisisRiesgoDatosInforme { Idactivo = AR.IdActivo, IdControl = AR.IdControl, Riesgo = AR.Riesgo, Activo = AE.Nombre, Coste = AI.CosteActivoInforme, Amenaza = AM.Amenaza, Valor = CE.ValorInforme }).Distinct().OrderBy(ln => ln.Riesgo).ThenBy(a => a.Coste).ToList();
            foreach (AnalisisRiesgoDatosInforme Analisis in LAnalisisRiesgo)
            {
                Analisis.Activo = Analisis.Activo + "\nRiesgo: " + Analisis.Riesgo + "\nCoste: " + Analisis.Coste;
                Analisis.Valor = ControlesEmpresaNegocio.DesSerializaRespuesta(Analisis.Valor);
            }
            return LAnalisisRiesgo;
        }

        //Método que recoge formateado el porcentaje de riesgo para cada informe y cada nivel de riesgo no aceptable y lo formatea para mostrarlo
        //en un gráfico de barras, agrupado por niveles de riesgo y los identificadores de los informes que hay en la lista LInformes
        public static List<PuntoDoubleXY> EvolucionNivelesRiesgoPorInformes(List<int> LInformes)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<PuntoDoubleXY> LPuntos = new List<PuntoDoubleXY>();
            List<int> NivelesRiesgoNoAceptables = new List<int>();
            NivelesRiesgoNoAceptables.Add(6); NivelesRiesgoNoAceptables.Add(4); NivelesRiesgoNoAceptables.Add(3);
            NivelesRiesgoNoAceptables.Add(2);
            foreach (int IdInforme in LInformes)
            {
                int NumeroTotalActivosInforme = ActivosInformeFactory.NumeroTotalesActivosEmpresaInforme(IdInforme);
                //Recorremos la lista de niveles de riesgo no aceptables y buscamos el número de activos de un informe
                //que están en el nivel actual de riesgo
                for (int i = 0; i < NivelesRiesgoNoAceptables.Count(); i++)
                {
                    int NivelRiesgoActual = NivelesRiesgoNoAceptables[i];
                    int NumeroActivosRiesgo = AnalisisRiesgoFactory.NumeroActivosNivelRiesgo(IdInforme, NivelRiesgoActual);
                    double PorcentajeRiesgoNivel = Math.Round(((double)NumeroActivosRiesgo / (double)NumeroTotalActivosInforme) * 100, 2);
                    PuntoDoubleXY nuevoPunto = new PuntoDoubleXY(NivelRiesgoActual.ToString(), PorcentajeRiesgoNivel, IdInforme.ToString());
                    LPuntos.Add(nuevoPunto);
                }
            }
            return LPuntos;
        }

        //Algoritmo para calcular el Análisis de Riesgos de una empresa según la base de conocimiento
        public static List<RiesgoActivo> CalcularAnalisisRiesgoBaseConocimiento(int IdEmpresa)
        {
            //ALGORTIMO PARA CALCULAR LA MATRIZ DE RIESGOS
            //Creamos la Estructura Principal
            ModeloContainer agenteBD = new ModeloContainer();
            List<RiesgoActivo> MatrizRiesgos = new List<RiesgoActivo>();
            //Sacamos el Nivel de Madurez Actual de la Empresa
            int MadurezActualEmpresa = EmpresasFactory.MadurezActualEmpresa(IdEmpresa);

            //Seleccionamos todos los activos actuales de la empresa
            List<ActivosEmpresa> ActivosTotEmpresa = ActivosEmpresaFactory.ActivosActuales(IdEmpresa);
            //Creamos un NuevoRiesgoActivo por Cada Activo de la Empresa. Le pasamos los valores de
            //la tabla ActivosEmpresa e Inicializamos la estructura CoberturaControlesAmenazaActivo
            //donde introduciremos después las Amenazas asociadas al activo
            foreach (ActivosEmpresa ActivoEmpresa in ActivosTotEmpresa)
            {
                RiesgoActivo NuevoRiesgoActivo = new RiesgoActivo();
                NuevoRiesgoActivo.IdActivo = ActivoEmpresa.IdActivo;
                NuevoRiesgoActivo.IdTipoActivo = ActivoEmpresa.IdTipoActivo;
                NuevoRiesgoActivo.CosteActivo = ActivoEmpresa.CosteActivo;
                NuevoRiesgoActivo.ValorActivo = ActivoEmpresa.ValorEstrategico;
                NuevoRiesgoActivo.CoberturaControlesAmenazaActivo = new List<NivelAmenaza>();
                MatrizRiesgos.Add(NuevoRiesgoActivo);

            }

            //Recorremos todos los activos
            for (int i = 0; i < MatrizRiesgos.Count(); i++)
            {
                //Cada vez que entremos en un Activo nuevo inicializamos el valor de contador a -1
                int AntiguaAmenaza = 0;
                int contador = -1;
                //De cada activo sacamos todas las amenazas y controles actuales asociados a ellas cuyo Nivel Madurez sea el Nivel
                //de madurez actual de la empresa.
                int IdTipoActivoActual = MatrizRiesgos[i].IdTipoActivo;
                var AmenazasControlesValores = (from MTAACR in agenteBD.Matriz_TipoActivosAmenazasCriteriosRiesgoEstablecer
                                                join MAC in agenteBD.Matriz_Amenazas_ControlesEstablecer on MTAACR.IdAmenaza equals MAC.IdAmenaza
                                                join CE in agenteBD.ControlesEmpresaEstablecer on MAC.IdControl equals CE.IdControl
                                                join C in agenteBD.ControlesEstablecer on CE.IdControl equals C.IdControl
                                                where CE.IdEmpresa == IdEmpresa && MTAACR.IdTipoActivo == IdTipoActivoActual
                                                      && C.NivelMadurez == MadurezActualEmpresa && MTAACR.Actual == true && MAC.Actual == true
                                                orderby MTAACR.IdTipoActivo, MAC.IdAmenaza
                                                select new { MTAACR.IdTipoActivo, MAC.IdAmenaza, CE, C.NivelMadurez }).Distinct().OrderBy(ln => ln.IdTipoActivo).ThenBy(a => a.IdAmenaza);
                foreach (var AmenContrValor in AmenazasControlesValores)
                {
                    int NuevaAmenaza = AmenContrValor.IdAmenaza;
                    //Si la Antigüa amenaza es distinta a la Nueva, creamos una instancia de NivelAmenaza
                    if (AntiguaAmenaza != NuevaAmenaza)
                    {
                        //Inicializamos a 0 el contador porque los controles estarán dentro de una nueva estructura
                        //de NivelAmenaza que a su vez será un elemento nuevo de la Lista CoberturaControlesAmenazaActivo.
                        //contador nos sirve para posicionarnos sobre la Lista CoberturaControlesAmenazaActivo
                        contador++;
                        AntiguaAmenaza = NuevaAmenaza;
                        //Actualizamos valor de contador para poder acceder al NivelAmenaza cuando lo creemos
                        NivelAmenaza NuevoNivelAmenaza = new NivelAmenaza();
                        NuevoNivelAmenaza.IdAmenaza = NuevaAmenaza;
                        //Creamos la estructura donde guardaremos los controles para dicha amenaza
                        NuevoNivelAmenaza.ControlesAmenaza = new List<ControlesCheckList>();
                        //Recogemos los valores del control asociado a esta tupla
                        ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValor.CE.IdEmpresa, AmenContrValor.CE.IdControl,
                                                                                 AmenContrValor.CE.Valor.Trim(), AmenContrValor.NivelMadurez);
                        //Añadimos el Control a la Amenaza que corresponde
                        NuevoNivelAmenaza.ControlesAmenaza.Add(NuevoControl);
                        //Añadimos la Amenaza Nueva al atributo CoberturaControlesAmenazaActivo del Activo
                        MatrizRiesgos[i].CoberturaControlesAmenazaActivo.Add(NuevoNivelAmenaza);
                    }
                    //Sino es porque la Amenaza es la misma y sólo nos queda insertar el control en su amenaza correspondiente
                    else
                    {
                        //Para saber en que Amenaza me encuentro uso la variable contador
                        ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValor.CE.IdEmpresa, AmenContrValor.CE.IdControl,
                                                                                 AmenContrValor.CE.Valor.Trim(), AmenContrValor.NivelMadurez);
                        //Insertamos el Control en la Estructura ControlesAmenaza de NivelAmenaza sirviéndonos de la variable
                        //contador para saber en que Amenaza me encuentro
                        MatrizRiesgos[i].CoberturaControlesAmenazaActivo[contador].ControlesAmenaza.Add(NuevoControl);

                    }
                }
                //Ahora llenamos los valores para coberturaControlesAmenazaVulnActivo
                //Cada vez que entremos en un Activo nuevo inicializamos el valor de contador a -1
                int AntiguaAmenazaP = 0;
                int contadorP = -1;
                //De cada activo sacamos todas las amenazas y controles actuales asociados a ellas (a través de las Vulnerabilidades
                //asociadas al IdTipoActivo del Activo en Cuestión y cuyo Nivel Madurez sea el Nivel
                //de madurez actual de la empresa
                IdTipoActivoActual = MatrizRiesgos[i].IdTipoActivo;
                var AmenazasControlesValoresP = (from MTV in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                 join MAV in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer on MTV.IdVulnerabilidad equals MAV.IdVulnerabilidad
                                                 join MAC in agenteBD.Matriz_Amenazas_ControlesEstablecer on MAV.IdAmenaza equals MAC.IdAmenaza
                                                 join CE in agenteBD.ControlesEmpresaEstablecer on MAC.IdControl equals CE.IdControl
                                                 join C in agenteBD.ControlesEstablecer on CE.IdControl equals C.IdControl
                                                 where CE.IdEmpresa == IdEmpresa && MTV.IdTipoActivo == IdTipoActivoActual
                                                       && C.NivelMadurez == MadurezActualEmpresa && MTV.Actual == true && MAV.Actual == true && MAC.Actual == true
                                                 select new { MTV.IdTipoActivo, MAC.IdAmenaza, CE, C.NivelMadurez }).Distinct().OrderBy(ln => ln.IdTipoActivo).ThenBy(a => a.IdAmenaza);
                //Se recorre cada elemento seleccionado anteriormente
                foreach (var AmenContrValorP in AmenazasControlesValoresP)
                {
                    int NuevaAmenazaP = AmenContrValorP.IdAmenaza;
                    //Si la Antigüa amenaza es distinta a la Nueva, creamos una instancia de NivelAmenaza
                    if (MatrizRiesgos[i].AmenazaNueva(NuevaAmenazaP))
                    {
                        if (AntiguaAmenazaP != NuevaAmenazaP)
                        {
                            //Inicializamos a 0 el contador porque los controles estarán dentro de una nueva estructura
                            //de ProbabilidadVulnerabilidad que a su vez será un elemento nuevo de la Lista CoberturaControlesAmenazaVulnActivo.
                            //contador nos sirve para posicionarnos sobre la Lista CoberturaControlesAmenazaVulnActivo
                            contadorP++;
                            AntiguaAmenazaP = NuevaAmenazaP;
                            //Actualizamos valor de contador para poder acceder al ProbabilidadVulnerabilidad cuando lo creemos
                            ProbabilidadVulnerabilidad NuevaProbVuln = new ProbabilidadVulnerabilidad();
                            //Como la Amenaza es Nueva introducimos el valor en el atributo
                            NuevaProbVuln.IdAmenaza = NuevaAmenazaP;
                            //Creamos la estructura donde guardaremos los controles para dicha amenaza
                            NuevaProbVuln.ControlesAmenazaVuln = new List<ControlesCheckList>();
                            //Recogemos los valores del control asociado a esta tupla
                            ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValorP.CE.IdEmpresa, AmenContrValorP.CE.IdControl,
                                                                                     AmenContrValorP.CE.Valor.Trim(), AmenContrValorP.NivelMadurez);
                            //Añadimos el Control a la Amenaza que corresponde
                            NuevaProbVuln.ControlesAmenazaVuln.Add(NuevoControl);
                            //Añadimos la Amenaza Nueva al atributo CoberturaControlesAmenazaActivo del Activo
                            MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo.Add(NuevaProbVuln);
                        }
                        //Sino es porque la Amenaza es la misma y sólo nos queda insertar el control en su amenaza correspondiente
                        else
                        {
                            //Para saber en que Amenaza me encuentro uso la variable contador
                            ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValorP.CE.IdEmpresa, AmenContrValorP.CE.IdControl,
                                                                                     AmenContrValorP.CE.Valor.Trim(), AmenContrValorP.NivelMadurez);
                            //Insertamos el Control en la Estructura ControlesAmenaza de NivelAmenaza sirviéndonos de la variable
                            //contador para saber en que Amenaza me encuentro
                            MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo[contadorP].ControlesAmenazaVuln.Add(NuevoControl);

                        }//Fin else
                    }

                }
            }


            //CalcularMatricesRiesgo
            //Una vez aquí ya tenemos todos los controles de Amenazas y Vulnerabilidades en las listas
            //coberturaControlesAmenazaActivo y coberturaControlesAmenazaVulnActivo de cada RiesgoActivo
            //Ahora tenemos que calcular las coberturas de los controles para cada amenaza de cada activo

            for (int i = 0; i < MatrizRiesgos.Count(); i++)
            {
                //Una vez aquí ya tenemos todos los controles de Amenazas y Vulnerabilidades en las listas
                //coberturaControlesAmenazaActivo y coberturaControlesAmenazaVulnActivo de cada RiesgoActivo
                //Ahora tenemos que calcular las coberturas de los controles para cada amenaza de cada activo
                //Para ello llamamos a CalculaCoberturaControlesAmenaza para cada elemento de MatrizRiesgos
                MatrizRiesgos[i].CalculaCoberturaControlesAmenaza();
                //Ordenamos las listas de NivelAmenaza y ProbabilidadVulnerabilidad según el Nivel de Riesgo
                MatrizRiesgos[i].CoberturaControlesAmenazaActivo.Sort();
                MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo.Sort();
                //Rellenamos los valores de NivelRiesgo con las Amenazas y con los controles que afectan
                //al activo
                MatrizRiesgos[i].CalculaNivelRiesgo();
                //Ordenamos la lista NivelRiesgo llamada NivelRiesgoAmenaza de mayor a menor Nivel de Riesgo
                MatrizRiesgos[i].NivelRiesgoAmenaza.Sort();
                //Introducimos a cada Activo el nivel Máximo de Riesgo al que está sometido
                MatrizRiesgos[i].NivelMaximoRiesgoActivo();
            }
            //Ordenamos la lista de Activos de Mayor a Menor Riesgo
            MatrizRiesgos.Sort();
            //Fin Calcular MatricesRiesgo
            return MatrizRiesgos;
        }

        //Método que devuelve una cadena con la lista de los Activos cuyos tipos de activos no están seleccionados en las relaciones de la empresa
        public static String TienenActivosRelacionesSeleccionadas(int IdEmpresa)
        {
            try
            {
                String TiposActivosSinRelaciones = "";
                List<int> LIdsTiposActivosSinRelaciones = new List<int>();
                ModeloContainer agenteBD = new ModeloContainer();
                if (IdEmpresa != -1)
                {
                    //Seleccionamos los activos actuales de la Empresa
                    IQueryable<ActivosEmpresa> ActivosTotEmpresa = from ActivEmp in agenteBD.ActivosEmpresaEstablecer
                                                                   where ActivEmp.IdEmpresa == IdEmpresa
                                                                   where ActivEmp.Actual == true
                                                                   select ActivEmp;
                    //Recorremos cada Activo actual buscando un tipo de relación asociada al Tipo Activo de dicho Activo
                    //Se busca que estén seleccionadas por cada Activo al menos una relación Tipo Activo - Amenaza - Criterio Riesgo o 
                    //Tipo Activo - Vulnerabilidad. Si no es así, se mandará un mensaje avisando que hay activos que faltan por tener asociadas
                    //algún tipo de relación
                    foreach (ActivosEmpresa Activo in ActivosTotEmpresa)
                    {
                        //Al principio se supone que el activo tiene relaciones en ambas instancias
                        bool hayRelTipActAmen = true;
                        bool hayRelTipActVuln = true;
                        //Se supone inicialmente que las matrices no tienen elementos con el IdTipoActivo actual
                        bool hayRelTipActAmenMatr = false;
                        bool hayRelTipActVulnMatr = false;
                        //Numero de relaciones Tipo Activo - Amenaza - Criterio Riesgo seleccionadas en la 
                        //tabla de instancia correspondiente con el IdTipoActivo del Activo que hay en la iteración actual
                        int NumRelTipActAmen = (from NRelTipActAmen in agenteBD.InstanciaTiposActivosAmenazasCriteriosRiesgoEstablecer
                                                where NRelTipActAmen.IdEmpresa == IdEmpresa && NRelTipActAmen.IdTipoActivo == Activo.IdTipoActivo && NRelTipActAmen.Actual == true
                                                select NRelTipActAmen).Count();
                        if (NumRelTipActAmen == 0)
                        {
                            hayRelTipActAmen = false;
                        }
                        //Numero de relaciones Tipo Activo - Vulnerabilidad seleccionadas en la 
                        //tabla de instancia correspondiente con el IdTipoActivo del Activo que hay en la iteración actual
                        int NumRelTipActVuln = (from NRelTipActVuln in agenteBD.InstanciaTiposActivosVulnerabilidadesEstablecer
                                                where NRelTipActVuln.IdEmpresa == IdEmpresa && NRelTipActVuln.IdTipoActivo == Activo.IdTipoActivo && NRelTipActVuln.Actual == true
                                                select NRelTipActVuln).Count();
                        if (NumRelTipActVuln == 0)
                        {
                            hayRelTipActVuln = false;
                        }
                        //Numero de relaciones Tipo Activo - Amenaza - Criterio Riesgo seleccionadas en la 
                        //tabla de matriz correspondiente con el IdTipoActivo del Activo que hay en la iteración actual
                        int NumRelTipActAmenMatr = (from NRelTipActAmenMatr in agenteBD.Matriz_TipoActivosAmenazasCriteriosRiesgoEstablecer
                                                    where NRelTipActAmenMatr.IdTipoActivo == Activo.IdTipoActivo && NRelTipActAmenMatr.Actual == true
                                                    select NRelTipActAmenMatr).Count();
                        //Si hay relaciones disponibles en la matriz se pone la bandera a true
                        if (NumRelTipActAmenMatr != 0)
                        {
                            hayRelTipActAmenMatr = true;
                        }
                        //Numero de relaciones Tipo Activo - Vulnerabilidad seleccionadas en la 
                        //tabla de matriz correspondiente con el IdTipoActivo del Activo que hay en la iteración actual
                        int NumRelTipActVulnMatr = (from NRelTipActVuln in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                    where NRelTipActVuln.IdTipoActivo == Activo.IdTipoActivo && NRelTipActVuln.Actual == true
                                                    select NRelTipActVuln).Count();
                        //Si hay relaciones disponibles en la matriz se pone la bandera a true
                        if (NumRelTipActVulnMatr != 0)
                        {
                            hayRelTipActVulnMatr = true;
                        }
                        //Si no existen instancias tanto en Tipo Activo - Amenaza - Criterio Riesgo como Tipo Activo - Vulnerabilidad
                        if ((!hayRelTipActAmen) && (!hayRelTipActVuln))
                        {
                            //Si además de lo anterior, se da el caso donde hay relaciones Tipo Activo - Amenaza - Criterio Riesgo o Tipo Activo - Vulnerabilidad
                            //en la base de conocimiento, entonces el usuario no ha elegido ninguna relación disponible
                            //para el IdTipoActivo del Activo y por tanto no pasa la validación
                            if ((hayRelTipActAmenMatr) || (hayRelTipActVulnMatr))
                            {
                                //Se recogen de cada activo el id de tipo de activo que no ha sido elegido en ningún tipo de relación
                                if (!LIdsTiposActivosSinRelaciones.Contains(Activo.IdTipoActivo))
                                {
                                    LIdsTiposActivosSinRelaciones.Add(Activo.IdTipoActivo);
                                }
                            }
                        }
                    }
                    foreach (int IdTipoActivo in LIdsTiposActivosSinRelaciones)
                    {
                        String NombreTipoActivo = TiposActivosFactory.RecogeNombreTipoActivo(IdTipoActivo);
                        TiposActivosSinRelaciones = TiposActivosSinRelaciones + "\n*-" + NombreTipoActivo;
                    }
                }
                //Se devuelve el String con los tipos de Activos que faltan por seleccionar. Si es "" quiere decir que todos
                //los activos tienen relaciones seleccionadas
                return TiposActivosSinRelaciones;
            }
            catch (Exception e1)
            {
                e1.ToString();
                return "No se pudieron recoger las relaciones";
            }
        }

        //Algoritmo del cálculo de análisis de riesgos según las relaciones de la empresa
        public static List<RiesgoActivo> CalculaAnalisRiesgoPorRelacionesEmpresa(int IdEmpresa)
        {
            //Creamos un NuevoRiesgoActivo por Cada Activo de la Empresa. Le pasamos los valores de
            //la tabla ActivosEmpresa e Inicializamos la estructura CoberturaControlesAmenazaActivo
            //donde introduciremos después las Amenazas asociadas al activo
            ModeloContainer agenteBD = new ModeloContainer();
            List<RiesgoActivo> MatrizRiesgos = new List<RiesgoActivo>();
            //Sacamos el Nivel de Madurez Actual de la Empresa
            int MadurezActualEmpresa = EmpresasFactory.MadurezActualEmpresa(IdEmpresa);

            //Seleccionamos todos los activos de la empresa
            //Seleccionamos todos los activos actuales de la empresa
            List<ActivosEmpresa> ActivosTotEmpresa = ActivosEmpresaFactory.ActivosActuales(IdEmpresa);
            foreach (ActivosEmpresa ActivoEmpresa in ActivosTotEmpresa)
            {
                RiesgoActivo NuevoRiesgoActivo = new RiesgoActivo();
                NuevoRiesgoActivo.IdActivo = ActivoEmpresa.IdActivo;
                NuevoRiesgoActivo.IdTipoActivo = ActivoEmpresa.IdTipoActivo;
                NuevoRiesgoActivo.CosteActivo = ActivoEmpresa.CosteActivo;
                NuevoRiesgoActivo.ValorActivo = ActivoEmpresa.ValorEstrategico;
                NuevoRiesgoActivo.CoberturaControlesAmenazaActivo = new List<NivelAmenaza>();
                MatrizRiesgos.Add(NuevoRiesgoActivo);

            }

            //Recorremos todos los activos
            for (int i = 0; i < MatrizRiesgos.Count(); i++)
            {
                //Cada vez que entremos en un Activo nuevo inicializamos el valor de contador a -1
                int AntiguaAmenaza = 0;
                int contador = -1;
                //De cada activo sacamos todas las amenazas y controles actuales asociados a las relaciones
                //Tipo Activo-Amenaza-Criterio Riesgo actuales seleccionadas, cuyo Nivel Madurez sea el Nivel
                //de madurez actual de la empresa
                int IdTipoActivoActual = MatrizRiesgos[i].IdTipoActivo;
                var AmenazasControlesValores = (from ITAACR in agenteBD.InstanciaTiposActivosAmenazasCriteriosRiesgoEstablecer
                                                join MAC in agenteBD.Matriz_Amenazas_ControlesEstablecer on ITAACR.IdAmenaza equals MAC.IdAmenaza
                                                join CE in agenteBD.ControlesEmpresaEstablecer on MAC.IdControl equals CE.IdControl
                                                join C in agenteBD.ControlesEstablecer on CE.IdControl equals C.IdControl
                                                where CE.IdEmpresa == IdEmpresa && ITAACR.IdTipoActivo == IdTipoActivoActual
                                                      && C.NivelMadurez == MadurezActualEmpresa && ITAACR.Actual == true && MAC.Actual == true
                                                orderby ITAACR.IdTipoActivo, MAC.IdAmenaza
                                                select new { ITAACR.IdTipoActivo, MAC.IdAmenaza, CE, C.NivelMadurez }).Distinct().OrderBy(ln => ln.IdTipoActivo).ThenBy(a => a.IdAmenaza);
                foreach (var AmenContrValor in AmenazasControlesValores)
                {
                    int NuevaAmenaza = AmenContrValor.IdAmenaza;
                    //Si la Antigüa amenaza es distinta a la Nueva, creamos una instancia de NivelAmenaza
                    if (AntiguaAmenaza != NuevaAmenaza)
                    {
                        //Inicializamos a 0 el contador porque los controles estarán dentro de una nueva estructura
                        //de NivelAmenaza que a su vez será un elemento nuevo de la Lista CoberturaControlesAmenazaActivo.
                        //contador nos sirve para posicionarnos sobre la Lista CoberturaControlesAmenazaActivo
                        contador++;
                        AntiguaAmenaza = NuevaAmenaza;
                        //Actualizamos valor de contador para poder acceder al NivelAmenaza cuando lo creemos
                        NivelAmenaza NuevoNivelAmenaza = new NivelAmenaza();
                        NuevoNivelAmenaza.IdAmenaza = NuevaAmenaza;
                        //Creamos la estructura donde guardaremos los controles para dicha amenaza
                        NuevoNivelAmenaza.ControlesAmenaza = new List<ControlesCheckList>();
                        //Recogemos los valores del control asociado a esta tupla
                        ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValor.CE.IdEmpresa, AmenContrValor.CE.IdControl,
                                                                                 AmenContrValor.CE.Valor.Trim(), AmenContrValor.NivelMadurez);
                        //Añadimos el Control a la Amenaza que corresponde
                        NuevoNivelAmenaza.ControlesAmenaza.Add(NuevoControl);
                        //Añadimos la Amenaza Nueva al atributo CoberturaControlesAmenazaActivo del Activo
                        MatrizRiesgos[i].CoberturaControlesAmenazaActivo.Add(NuevoNivelAmenaza);
                    }
                    //Sino es porque la Amenaza es la misma y sólo nos queda insertar el control en su amenaza correspondiente
                    else
                    {
                        //Para saber en que Amenaza me encuentro uso la variable contador
                        ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValor.CE.IdEmpresa, AmenContrValor.CE.IdControl,
                                                                                 AmenContrValor.CE.Valor.Trim(), AmenContrValor.NivelMadurez);
                        //Insertamos el Control en la Estructura ControlesAmenaza de NivelAmenaza sirviéndonos de la variable
                        //contador para saber en que Amenaza me encuentro
                        MatrizRiesgos[i].CoberturaControlesAmenazaActivo[contador].ControlesAmenaza.Add(NuevoControl);

                    }
                }
                //Ahora llenamos los valores para coberturaControlesAmenazaVulnActivo
                //Cada vez que entremos en un Activo nuevo inicializamos el valor de contador a -1
                int AntiguaAmenazaP = 0;
                int contadorP = -1;
                //De cada activo sacamos todas las amenazas y controles asociados a ellas (a través de las
                //relaciones TipoActivo-Vulnerabilidade actuales seleccionadas por la empresa y cuyo Nivel Madurez sea el Nivel
                //de madurez actual de la empresa
                IdTipoActivoActual = MatrizRiesgos[i].IdTipoActivo;
                var AmenazasControlesValoresP = (from ITV in agenteBD.InstanciaTiposActivosVulnerabilidadesEstablecer
                                                 join MAV in agenteBD.Matriz_AmenazasVulnerabilidadesEstablecer on ITV.IdVulnerabilidad equals MAV.IdVulnerabilidad
                                                 join MAC in agenteBD.Matriz_Amenazas_ControlesEstablecer on MAV.IdAmenaza equals MAC.IdAmenaza
                                                 join CE in agenteBD.ControlesEmpresaEstablecer on MAC.IdControl equals CE.IdControl
                                                 join C in agenteBD.ControlesEstablecer on CE.IdControl equals C.IdControl
                                                 where CE.IdEmpresa == IdEmpresa && ITV.IdTipoActivo == IdTipoActivoActual
                                                       && C.NivelMadurez == MadurezActualEmpresa && ITV.Actual == true && MAV.Actual == true && MAC.Actual == true
                                                 select new { ITV.IdTipoActivo, MAC.IdAmenaza, CE, C.NivelMadurez }).Distinct().OrderBy(ln => ln.IdTipoActivo).ThenBy(a => a.IdAmenaza);
                //Para cada elemento recogido en la query anterior
                foreach (var AmenContrValorP in AmenazasControlesValoresP)
                {
                    int NuevaAmenazaP = AmenContrValorP.IdAmenaza;
                    if (MatrizRiesgos[i].AmenazaNueva(NuevaAmenazaP))
                    {
                        //Si la Antigüa amenaza es distinta a la Nueva, creamos una instancia de NivelAmenaza
                        if (AntiguaAmenazaP != NuevaAmenazaP)
                        {
                            //Inicializamos a 0 el contador porque los controles estarán dentro de una nueva estructura
                            //de ProbabilidadVulnerabilidad que a su vez será un elemento nuevo de la Lista CoberturaControlesAmenazaVulnActivo.
                            //contador nos sirve para posicionarnos sobre la Lista CoberturaControlesAmenazaVulnActivo
                            contadorP++;
                            AntiguaAmenazaP = NuevaAmenazaP;
                            //Actualizamos valor de contador para poder acceder al ProbabilidadVulnerabilidad cuando lo creemos
                            ProbabilidadVulnerabilidad NuevaProbVuln = new ProbabilidadVulnerabilidad();
                            //Como la Amenaza es Nueva introducimos el valor en el atributo
                            NuevaProbVuln.IdAmenaza = NuevaAmenazaP;
                            //Creamos la estructura donde guardaremos los controles para dicha amenaza
                            NuevaProbVuln.ControlesAmenazaVuln = new List<ControlesCheckList>();
                            //Recogemos los valores del control asociado a esta tupla
                            ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValorP.CE.IdEmpresa, AmenContrValorP.CE.IdControl,
                                                                                     AmenContrValorP.CE.Valor.Trim(), AmenContrValorP.NivelMadurez);
                            //Añadimos el Control a la Amenaza que corresponde
                            NuevaProbVuln.ControlesAmenazaVuln.Add(NuevoControl);
                            //Añadimos la Amenaza Nueva al atributo CoberturaControlesAmenazaActivo del Activo
                            MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo.Add(NuevaProbVuln);
                        }
                        //Sino es porque la Amenaza es la misma y sólo nos queda insertar el control en su amenaza correspondiente
                        else
                        {
                            //Para saber en que Amenaza me encuentro uso la variable contador
                            ControlesCheckList NuevoControl = new ControlesCheckList(AmenContrValorP.CE.IdEmpresa, AmenContrValorP.CE.IdControl,
                                                                                     AmenContrValorP.CE.Valor.Trim(), AmenContrValorP.NivelMadurez);
                            //Insertamos el Control en la Estructura ControlesAmenaza de NivelAmenaza sirviéndonos de la variable
                            //contador para saber en que Amenaza me encuentro
                            MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo[contadorP].ControlesAmenazaVuln.Add(NuevoControl);

                        }//Fin else
                    }
                }
            }


            //CalcularMatricesRiesgo
            //Una vez aquí ya tenemos todos los controles de Amenazas y Vulnerabilidades en las listas
            //coberturaControlesAmenazaActivo y coberturaControlesAmenazaVulnActivo de cada RiesgoActivo
            //Ahora tenemos que calcular las coberturas de los controles para cada amenaza de cada activo

            for (int i = 0; i < MatrizRiesgos.Count(); i++)
            {
                //Una vez aquí ya tenemos todos los controles de Amenazas y Vulnerabilidades en las listas
                //coberturaControlesAmenazaActivo y coberturaControlesAmenazaVulnActivo de cada RiesgoActivo
                //Ahora tenemos que calcular las coberturas de los controles para cada amenaza de cada activo
                //Para ello llamamos a CalculaCoberturaControlesAmenaza para cada elemento de MatrizRiesgos
                MatrizRiesgos[i].CalculaCoberturaControlesAmenaza();
                //Ordenamos las listas de NivelAmenaza y ProbabilidadVulnerabilidad según el Nivel de Riesgo
                MatrizRiesgos[i].CoberturaControlesAmenazaActivo.Sort();
                MatrizRiesgos[i].CoberturaControlesAmenazaVulnActivo.Sort();
                //Rellenamos los valores de NivelRiesgo con las Amenazas y con los controles que afectan
                //al activo
                MatrizRiesgos[i].CalculaNivelRiesgo();
                //Ordenamos la lista NivelRiesgo llamada NivelRiesgoAmenaza de mayor a menor Nivel de Riesgo
                MatrizRiesgos[i].NivelRiesgoAmenaza.Sort();
                //Introducimos a cada Activo el nivel Máximo de Riesgo al que está sometido
                MatrizRiesgos[i].NivelMaximoRiesgoActivo();
            }
            //Ordenamos la lista de Activos de Mayor a Menor Riesgo
            MatrizRiesgos.Sort();
            return MatrizRiesgos;
        }

    }
}
